//
//  ActiveAIChatExt.swift
//  imprint
//
//  Created by 小柠檬🍋 on 2025/3/11.
//

import Foundation
import SwiftUI

//ai记忆
class ActiveAIMemoryExt : BaseViewModel {
    static let instance = ActiveAIMemoryExt()
    private var mapMemory: [String: [AiMemoryBean]] = [:]

    private let modeType = IAiModelType.memory.rawValue
    private let tag = "checkMemory"
    
    func checkAIMemory() {
        request(isLoading: false,timeout: 60 * 10) {
            try check(AppStorageManager.shared.toggleAi) {
                "AI 功能已关闭"
            }
            try check(self.tag, AppStorageManager.shared.toggleMemory) {
                "记忆提取功能关闭"
            }
            let listAiRole = try await BackupsManager.shared.getDelegateConfig()?.getAiRoleList(false) ?? []
            for aiRole in listAiRole {
                if !aiRole.select {
                    //                    showLof(tag, "非选中无法提取")
                    continue
                }
                //todo 聊天记忆提取信息
                let listChat = try await BackupsManager.shared.getDelegateDiary()?.queryMemoryChat(aiUserId: aiRole.objectId ?? "", userId: BackupsManager.shared.backupsType == BackupsType.cloud ? userManager.getUserId() : "", pageNo: 0, pageSize: 100) ?? []
                let listNewChat:[ChatBean] = listChat.reversed()//由于记忆提取记录是倒序，使用reversed转换成升序
                showLog(self.tag, "\(aiRole.name ?? "")聊天数量\(listNewChat.count)")

                //todo 日记记忆提取信息
                let listDiary = try await BackupsManager.shared.getDelegateDiary()?.queryMemoryDiary(aiUserId: aiRole.objectId ?? "", userId: BackupsManager.shared.backupsType == BackupsType.cloud ? userManager.getUserId() : "", pageNo: 0, pageSize: 20) ?? []
                showLog(self.tag, "\(aiRole.name ?? "")日记数量\(listDiary.count)")
                await MainActor.run {
                    self.doAiReply(aiRole, listNewChat, listDiary, IRoleType.BOT.rawValue)
                }
            }
            
            //todo 我的日记记忆提取信息
            let listMyDiary = try await BackupsManager.shared.getDelegateDiary()?.queryMemoryDiary(aiUserId: nil, userId: BackupsManager.shared.backupsType == BackupsType.cloud ? userManager.getUserId() : "", pageNo: 0, pageSize: 50) ?? []
            await MainActor.run {
                self.doAiReply(nil, nil, listMyDiary, IRoleType.USER.rawValue)
            }
            showLog(self.tag, "我的日记数量\(listMyDiary.count)")

        } suc: {
            
        } fail: {
            showLog(self.tag, $0.message)
        }
    }
    
    func doAiReply(_ aiRole: AiRoleBean?, _ listChat:[ChatBean]? , _ listDiary:[DiaryBean], _ roleType: Int, _ backup: Bool = false) {
        showLog(tag, "提取\(aiRole?.name ?? "")的记忆")
        var errorApi = ""
        request(isLoading: false,timeout: 60 * 5) {
            
            try check(self.tag, (listChat ?? []).count > 50 || (listDiary.count) > 7) {
                "\(aiRole?.name ?? ""):数量不够"
            }
            try check(self.tag, AiChatExt.isAiEnabled() || AiCustomUtils.shared.isCustomAi(type: self.modeType)) {
                "AI 功能已用尽,请前往活动领取次数"
            }
            let botRoleBean = aiRole != nil ? RoleBean.get(aiRole!) : nil
            var replyStr : String = ""
            if backup {
                //启动备用方案
                try await retry(maxRetries: 3, retryDelayMillis: 500) {
                    let aiModeBean = configManager.getConfig().getAiChatMode2(key: self.modeType)
                    errorApi = "\(aiModeBean.host ?? ""),\(aiModeBean.model ?? "")"
                    let bean = AIMemoryRequestBean(model : aiModeBean.model, botRoleBean: botRoleBean, list: listChat ?? [], listDiary: listDiary)
                    showLog(self.tag, "请求AI：\(bean)")
                    let result = try await AiNetManager.shared.requestAI(host: aiModeBean.host, token: aiModeBean.token, jsonObject: bean, modeType: AIChatResultBean.self)
                    replyStr = result.getReplyStr()
                    showLog(self.tag, replyStr)
                }
            } else if AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                //自定义
                try await retry(maxRetries: 3, retryDelayMillis: 500) {
                    let host = AiCustomUtils.shared.getCustomHost(type: self.modeType)
                    let token = AiCustomUtils.shared.getCustomToken(type: self.modeType)
                    let model = AiCustomUtils.shared.getCustomModel(type: self.modeType)
                    errorApi = "\(host),\(model)"
                    let bean = AIMemoryRequestBean(model : model, botRoleBean: botRoleBean, list: listChat ?? [], listDiary: listDiary)
                    showLog(self.tag, "请求AI：\(bean)")
                    let result = try await AiNetManager.shared.requestAI(host: host, token: token, jsonObject: bean, modeType: AIChatResultBean.self)
                    replyStr = result.getReplyStr()
                    showLog(self.tag, replyStr)
                }
            } else {
                //配置模型
                try await retry(maxRetries: 1, retryDelayMillis: 500) {
                    let aiModeBean = configManager.getConfig().getAiChatMode(key: self.modeType)
                    errorApi = "\(aiModeBean.host ?? ""),\(aiModeBean.model ?? "")"
                    let bean = AIMemoryRequestBean(model : aiModeBean.model, botRoleBean: botRoleBean, list: listChat ?? [], listDiary: listDiary)
                    showLog(self.tag, "请求AI：\(bean)")
                    let result = try await AiNetManager.shared.requestAI(host: aiModeBean.host, token: aiModeBean.token, jsonObject: bean, modeType: AIChatResultBean.self)
                    replyStr = result.getReplyStr()
                    showLog(self.tag, replyStr)
                }
            }
            showLog(self.tag, "回复内容：\(replyStr)")
            //保存记忆
            let aiMemoryBean = AiMemoryBean()
            aiMemoryBean.content = replyStr
            aiMemoryBean.count = replyStr.count
            aiMemoryBean.roleType = roleType
            aiMemoryBean.aiRoleId = aiRole?.objectId
            aiMemoryBean.userId = userManager.getUserId()
            aiMemoryBean.createTime = getMillisecond(Date().timeIntervalSince1970)
            aiMemoryBean.updateTime = aiMemoryBean.createTime
            try check(self.tag, aiMemoryBean.count > 20) {
                "提取数量太少，无法提取"
            }
            try await BackupsManager.shared.getDelegateDiary()?.addMemory(bean: aiMemoryBean)
            //保存数据
            for it in listChat ?? [] {
                it.memory = true
                try await retry(maxRetries: 3, retryDelayMillis: 500) {
                    try await BackupsManager.shared.getDelegateDiary()?.saveChat(bean: it)
                }
            }
            for it in listDiary {
                it.memory = true
                try await retry(maxRetries: 3, retryDelayMillis: 500) {
                    try await BackupsManager.shared.getDelegateDiary()?.saveDiary(bean: it)
                }
            }
        } suc: {
            //执行获取记忆
            self.doMemoryStr()
            if !AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                AiChatExt.deductAiChatCount(1)
            }
            //存储当前存储过了
        } fail: { it in
            if ERROR.NET_ERRPR.rawValue == it.code {
                AiChatExt.reportError(
                    type: self.modeType,
                    typeName: "记忆提取错误",
                    message: it.realMessage,
                    errorApi: errorApi)
                
                if let error = configManager.getConfig().getAiError(content: it.realMessage) {
                    showToast(error)
                }
            } else if ERROR.CHECK_ERRPR.rawValue != it.code{
                //非自定义使用备用方案
                if !backup && !AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                    showLog(self.tag, "记忆提取使用备用方案")
                    self.doAiReply(aiRole, listChat, listDiary, roleType, true)
                }
            }
            
        }
    }
    
    //获取记忆内容，启动app调用一次
    func doMemoryStr() {
        showLog(tag, "开始获取记忆")
        request(isLoading: false,timeout: 60 * 3) {
            try await self.doMemoryStr(role: nil)
            let list = try await BackupsManager.shared.getDelegateConfig()?.getAiRoleList(false) ?? []
            for role in list {
                if (role.select) {
                    try await self.doMemoryStr(role: role)
                }
            }
            return true
        } suc: { _ in
            
        } fail: {
            showLog(self.tag, $0.message)
        }
    }
    
    //获取某个角色的记忆
    private  func doMemoryStr(role: AiRoleBean?) async throws  {
        if (role == nil) {
            //我的记忆
            showLog(tag, "开始获取我的记忆")
            let listMy = try await BackupsManager.shared.getDelegateDiary()?.queryMyNewChatMemory(userId: userManager.getUserId()) ?? []
            if (listMy.isEmpty == false ) {
                mapMemory["my"] = listMy
            }
        } else {
            //心灵记忆
            showLog(tag, "开始获取‘\(String(describing: role?.name))’记忆")
            try await retry(maxRetries: 5, retryDelayMillis: 200) {
                let listAi = try await BackupsManager.shared.getDelegateDiary()?.queryNewChatMemory(aiRoleId: role?.objectId ?? "", userId: userManager.getUserId()) ?? []
                if (listAi.isEmpty == false ) {
                    self.mapMemory[role?.objectId ?? ""] = listAi
                }
            }
        }
    }
    
    func getAiMemoryStr(botRoleBean: RoleBean) -> String {
        var listAll: [String] = []
        
        // 处理"my"对应的记忆
        if let myMemories = mapMemory["my"] {
            listAll.append("#'\(String(describing: botRoleBean.name2))'的一些日记信息：")
            let randomMemories = getRandomList(list: myMemories)
            listAll.append(contentsOf: randomMemories.map { $0.content ?? "" })
        }
        
        // 处理角色对应的记忆
        if let roleMemories = mapMemory[botRoleBean.roleId ?? ""] {
            listAll.append("#'\(botRoleBean.name ?? "")'和'\(botRoleBean.name2 ?? "")'之间的关键记忆与事件：")
            let randomMemories = getRandomList(list: roleMemories)
            listAll.append(contentsOf: randomMemories.map { $0.content ?? "" })
        }
        
        return listAll.joined(separator: "\n")
    }
    
    func getRandomList(list: [AiMemoryBean]) -> [AiMemoryBean] {
        return list.getRandomSubList(count: configManager.getConfig().aiChat.aiMemoryInjectCount).sorted { $0.createTime < $1.createTime }
    }
}
